#include "NessEngine.h"
#include <vector>

int tempY;
string eType, cType, ID;

int newX;
int newY;

EntityFactory factory;

class Bullet : public Entity{
public:
	Bullet();
	~Bullet();
};

const int MENU = 0, GAME = 1;
int state = MENU;
const int MENU_main = 0, MENU_sub1 = 1, MENU_sub2 = 2;
int menuState = MENU_main;
const int NOLEVEL = 0, LEVEL1 = 1, LEVEL2 = 2; //and so on
int gameState = NOLEVEL;

int main(int argc, char *argv[]){

	NessEngineSys engine;
	
	engine.InitSystem(640,480);

	float x = 16, y = 480/2, rotate = 0, rotate2 = 360;
	float firstVel = 0.78f;

	//create the player
	factory.MakeEntity("PLAYER","USER","player");
	Entity *player;
	player = factory.getEntity("player");
	if(!player->texture.LoadTexture("image.png"))
		cout << "Failed to load image.png\n";
	player->tileSheet=false;
	player->SetP(x,y);
	player->SetB(32,32);

	//enemy type 1
	Entity *enemies[5];
	for(int i = 0; i < 5; i++){
		enemies[i] = new Entity;
		if(!enemies[i]->texture.LoadTexture("enemy1.png"))
			return 1;
		enemies[i]->SetB(32,32);
		enemies[i]->SetP(600,i*32+i*i*i+150);
		enemies[i]->tileSheet=false;
	}
	if(!enemies[2]->texture.LoadTexture("test.png"))
		return 1;

	Entity *bullet[20];
	for(int i = 0; i < 20; i++){
		bullet[i]=new Entity;
		if(!bullet[i]->texture.LoadTexture("bullet.png"))
			return 1;
		bullet[i]->SetP(5,5);
		bullet[i]->SetB(10,10);
		bullet[i]->tileSheet=false;
	}

	vector<Entity*> bullets;

	double m = 0, a = 0, yint = 0;

	int gState = 0;

	//timer variables
	int t = 0;
	int n = 0;

	float timer = 0;
	float decre = 15;
	int bulletCount = 0;
	int totalFires = 0;

	while(!engine.sysDone){
		//handle events and update keystates
		engine.UpdateEvents();

		if(state==MENU){
			if(menuState==MENU_main){
				if(engine.key[SDLK_RETURN]){
					gameState=LEVEL1;
					state=GAME;
				}
			}//end menuState=MENU_main
			else if(menuState==MENU_sub1){
				
			}//end menuState=MENU_sub1

		}//end state=MENU
		else if(state==GAME){
			//if the state of the program = GAME the player is rendered
			if(engine.key[SDLK_RIGHT])
				player->MoveX(RIGHT);
			else if(engine.key[SDLK_LEFT])
				player->MoveX(LEFT);
			if(engine.key[SDLK_DOWN])
				player->MoveY(DOWN);
			else if(engine.key[SDLK_UP])
				player->MoveY(UP);

			if(player->GetX()<16)
				player->SetX(16);
			if(player->GetX()>640-16)
				player->SetX(64);
			if(player->GetY()<16)
				player->SetY(16);
			if(player->GetY()>480-16)
				player->SetY(480-16);

			engine.StartMatrix(player);
			engine.RotateEntity(player,rotate);
			engine.Render(player);
			engine.EndMatrix();
			//if the state of the program = GAME and its state is LEVEL1, do this shit
			if(gameState==LEVEL1){
				if(bulletCount>19){
					bulletCount=0;
				}
				if(engine.key[SDLK_SPACE]&&(timer==0)){
					if(totalFires<20)
						bullets.push_back(bullet[bulletCount]);
		
					bullets[bulletCount]->SetY(player->GetY());
					bullets[bulletCount]->SetX(player->GetX());
					
					bulletCount++;
					totalFires++;
					timer=decre/60;
				}
				else if(engine.key[SDLK_SPACE]&&timer>0){
					decre--;
					timer=decre/60;
					if(decre==0){
						timer=0;
						decre=15;
					}
				}
				else{
					timer=0;
					decre=15;
				}

				if(enemies[1])
					enemies[1]->box.x-=3;
				if(enemies[2])
					enemies[2]->box.x-=3;
				if(enemies[0])
					enemies[0]->box.x-=4;
				if(enemies[4])
					enemies[4]->box.x-=6;				
				if(enemies[3]){
					enemies[3]->box.x-=3;
					enemies[3]->box.y = 90*sin((double)enemies[3]->box.x*1/100)+64;
				}			

				for(int i = 0; i < 2; i++){
					if(enemies[i]){
						engine.StartMatrix(enemies[i]);
						engine.Render(enemies[i]);
						engine.EndMatrix();
					}
				}
				for(int i = 3; i < 5; i++){
					if(enemies[i]){
						engine.StartMatrix(enemies[i]);
						engine.Render(enemies[i]);
						engine.EndMatrix();
					}
				}
				for(int i = 0; i < 5; i++){
					if(enemies[i]){
						if(engine.EntityCollision(player,enemies[i])||enemies[i]->box.x<-16)
							enemies[i]->box.x=1280;
					}
				}
				
				if(enemies[2]){
					engine.StartMatrix(enemies[2]);
					engine.RotateEntity(enemies[2],rotate2);
					engine.Render(enemies[2]);
					engine.EndMatrix();
				}
				//render bullets
				if(bullets.size()>0){
					for(int i = 0; i < bullets.size(); i++){
						bullets[i]->box.x+=bullets[i]->speed;
						engine.StartMatrix(bullets[i]);
						engine.Render(bullets[i]);
						engine.EndMatrix();
						for(int j = 0; j < 5; j++){
							if(enemies[j]){
								if(engine.EntityCollision(bullets[i],enemies[j])){
									bullets[i]->box.y = 10000;
									bullets[i]->tempTick++;
									enemies[j]->box.x=1280;
								}
							}
						}
						if(bullets[i]->box.x>646){
							bullets[i]->tempTick++;
							bullets[i]->box.y = 10000;
						}
					}
				}			
			}//end gameState=LEVLEL1
			
		}//end state=GAME
		//update system
		engine.UpdateSystem(60);
		if(engine.key[SDLK_ESCAPE])
			engine.sysDone=true;
	}

	return 0;
}
